\documentclass{article}
\usepackage[utf8]{inputenc}
%\usepackage[T1]{fontenc}  
\usepackage[english]{babel}

\usepackage{listings}
\lstset{
%language=C,
basicstyle=\footnotesize,
numbers=left,
numberstyle=\normalsize,
breaklines=true,  
numbersep=7pt,
frame=single,
}


\title{GLOW Pogrammer's Manual}
\author{Glow developpement team}
\date{8/04/2011}


\begin{document}
\maketitle
\newpage

	\section*{Presentation}
	
		\subsection*{Special thanks}
		We want to thanks Mr Jubertie to give us the opportunity to work on OpenGL as
		final study project and also for his welcome help and his diponibility. We also
		want to thanks Mr Melin for his OpenGL courses which give us the capacity to
		make this project.
		
		\subsection*{Introduction}
		Glow is an OpenGL based library. Its goal is to simplify the 3D programation using
		OpenGL. We want to supply an easy, but complete, interface which allows the loading
		of meshes from files, texturing, lighting and shading a scene. This library stands 
		on a completly oriented object architecture. We hope you will find it helpful.
\newpage
\tableofcontents
\newpage

	\section{Getting started}
	
		\subsection{Get, compile and install Glow}
			You can get the Glow Library with a checkout on our repository.
			Then you have to enter make one time, then sudo make install if you want to
			install libGlow.so on you /usr/lib directory. Or just a second make if you 
			want to get the dynamic libray. You can now use it. 
			
	\section{Window Device and Event Loop}
		\subsection{The Window}
					You're about to open your first Glow Window.
			First, you will have to get a pointer to the singleton GlowDevice.
			
			\begin{lstlisting}
GlowDevice *device = GlowDevice::getInstance();
			\end{lstlisting}
			
			Once you have started the device you wille have to initialize it with the init function.
			It takes three parameters. Two integers for the window width and height, and a
			boolean for activate or not the fullscreen mode. 
			
			\begin{lstlisting}
bool init(int width, int height, bool fullScreen);
			\end{lstlisting}
			
			When the device is launched, you can set the window's title by calling the function setWindowTitle with a 
			string parametter.
			
			\begin{lstlisting}
void setWindowTitle (std::string title);
			\end{lstlisting}
			
			And a pointer to the renderer to get the window's OpenGL context.
			
			\begin{lstlisting}
Renderer *rdr = device->getRenderer();
			\end{lstlisting}
			
			You have a beautyful empty window, but you wille also have to get a pointer to the event manager,
			and start the event loop.
			
			\begin{lstlisting}
EventManager *emgr = device->getEventManager();
while(!emgr->quit())
{
	//do something
}
			\end{lstlisting}
			
\newpage
			If we sum up what we have, we get this code : 
			
			\begin{lstlisting}
int main(char argc, char ** argv)
{
	GlowDevice *device = GlowDevice::getInstance();
	device->init(800, 600, false);
	device->setWindowTitle("first window");
	Renderer *rdr = device->getRenderer();
	EventManager *emgr = device->getEventManager();
	while(!emgr->quit())
	{
		//do something
	}
	GlowDevice::destroy();
	return 0;
}
			\end{lstlisting}
		

			This will open an empty black window, but it can do nothing, you have to
			deal with events. Note that you have to destroy the device befor exit the program.
			
		\subsection{The Event Manager}
			The event manager is a class which allows you to analyze which key is pressed
			or where is the mouse's pointer. At each event loop's turn you need to call 
			the getEvent function. It updates the states of the pressed keys and the position
			of the mouse. You can use the boolean function quit() to test if the window has received
			a close message (a clic on the cross).
			
		\subsection{Keybord Input}
			To test if a keyboard key is pressed you have to use the boolean function 
			isKeyDownOnce and give it the character you will test.
			For exemple :
			
			\begin{lstlisting}
if (emgr->isKeyDownOnce('a'))
	cout << "The a key is pressed" << endl;
			\end{lstlisting} 
			
			However if the key stay pressed after the function will return false.
			You can also use the function isKeyDown for test a continue input. The function
			will return true while the key is pressed.
			
			For keys which are differents to the ASCII printable character you can give as
			parametter of those two functions a constant value defined in the GLFW library
			(see the GLFW doc). 
			
		\subsection{Mouse Input}
			Glow allows you to manage also with mouse event. You can get the coordinates of
			the pointer with the functions getMouseX and getMouseY. You can also get the
			relative position of the pointer (i.e. the difference between the position in
			the previous frame and the actual position). If you want to test the activation
			of a mouse button, use the function isMouseButtonUp with a parametter representing
			the button, defined in the GLFW library (see the GLFW doc).

			To finish with events we take the previous example.
			
			\begin{lstlisting}
int main(char argc, char ** argv)
{
	GlowDevice *device = GlowDevice::getInstance();
	device->init(800, 600, false);
	device->setWindowTitle("first window");
	Renderer *rdr = device->getRenderer();
	EventManager *emgr = device->getEventManager();
	while(!emgr->quit())
	{
		if (emgr->isKeyDownOnce('a'))
			cout << "The a key is pressed" << endl;
		
		if (emgr->isKeyDown('x')
			cout << "mouse x position : " << emgr->getMouseX();
			
		if (emgr->isKeyDown('y')
			cout << "mouse y position : " << emgr->getMouseY();
	}
	GlowDevice::destroy();
	return 0;
}
			\end{lstlisting}
			The window is still empty, but it reacts to the events. Now we will add a 
			camera.
	
	\section{Camera}
		Without a camera you will see nothing. This object allows you to project the scene
		on the screen. There are differents kinds of cameras. You have a fixed one and a free 
		fly one.
	
		\subsection{Fixed Camera}
		The fixed camera always shows the same section of the scene. You can use it simply 
		by calling the function lookAt of the Renderer. This function takes two vectors as
		parametters. Vector3D is an object which encapsulates a float triplet. The first
		vector is the position of the camera and the second where it looks.
		\newpage
		\begin{lstlisting}
int main(char argc, char ** argv)
{
	GlowDevice *device = GlowDevice::getInstance();
	device->init(800, 600, false);
	device->setWindowTitle("first window");
	Renderer *rdr = device->getRenderer();
	EventManager *emgr = device->getEventManager();
	while(!emgr->quit())
	{
		if (emgr->isKeyDownOnce('a'))
			cout << "The a key is pressed" << endl;
		
		if (emgr->isKeyDown('x')
			cout << "mouse x position : " << emgr->getMouseX();
			
		if (emgr->isKeyDown('y')
			cout << "mouse y position : " << emgr->getMouseY();
			
		rdr->lookAt(Vector3D(3.0, 2.0, 3.0), Vector3D(0.0, 0.0, 0.0));
	}
	GlowDevice::destroy();
	return 0;
}
		\end{lstlisting}
		
		This will put the camera in (3,2,3) and makes it looks in (0,0,0). This camera can
		be usefull in some cases but not convenient when you need to move it at each frames.
		You will need for that a free fly camera. 
		
		\subsection{Free Fly Camera}
		Free Fly Camera is controlled by mouse and keybord input. Four keys move the camera,
		one augment the deplacement speed. The main direction is determined with the
		mouse's movement. You don't need to deal with the events which manage the camera.
		It has five string commands : 
		\begin{itemize}
		\item[*]forward : move forward, default value 'z'
		\item[*]backward : move backward, default value 's'
		\item[*]left : move left, default value 'q'
		\item[*]right : move right, default value 'd'
		\item[*]boost : move faster, default value left shift key
		\end{itemize}
		
		For choosing which key will correspond to what command, create an instance of KeyMap
		and, for each command, give a character,or a GLFW value. It will be the trigger
		which launch the command.
		
		\newpage
		\begin{lstlisting}
KeyMap myPattern;
myPattern["forward"] = 'o'; //choose your key event here
myPattern["backward"] = 'l'; //choose your key event here
myPattern["left"] = 'k'; //choose your key event here
myPattern["right"] = 'm'; //choose your key event here
myPattern["boost"] = 'b'; //choose your key event here
		\end{lstlisting}
		
		Once you have your KeyMap instance you need to choose the initial position of the
		camera. You need a Vector3D.
		
		\begin{lstlisting}
Camera myCamera(Vector3D(3.0,2.0,3.0));
mycamera.setKeyMap(myPattern);
		\end{lstlisting}
		
		If you preafer to use the default pattern, you don't have
		to declare a KeyMap, you juste have to choose the first position of your camera.
		Now for each turn of the main loop, your camera need to receive the events and move
		according to your pattern.
				
		\begin{lstlisting}
myCamera.getEvent();
myCamera.animate();
		\end{lstlisting}
		
		You can set the camera's sensivity to the mouse's mouvments and speed with
		
		\begin{lstlisting}
myCamera.setSensivity(1.0);
myCamera.setSpeed(5.0);
		\end{lstlisting}
		
		The camera works, but the window stay still empty, it is time to add some 3D objects
		in it !
		
	\section{Loading Meshes}
		\subsection{3D Objects}
			A 3D object is represented by a mesh, this mesh is useful to keep the datas 
			of the 3D object. Its vertices, texture coodinates, normal arrays and
			their size. The mesh's material is also stored. Those 
			datas are loaded or calculated from off, obj and mnt files.
			
		\subsection{From Vertices Files}
			Currently only mnt, obj and off files are managed by Glow. All you have to do is
			to get get a pointer to a Mesh and give the name of the file you want to
			load. By default, the mesh is loaded using Vertex Buffers Objects.
			
			\begin{lstlisting}
Mesh *myMesh = MeshFactory::create("myFile.off");
			\end{lstlisting}
			
			Then at each turn of the main loop you will call the draw function of your mesh.
			
			\begin{lstlisting}
myMesh->draw();
			\end{lstlisting}
			
			To sum it up in one code  : 
			
			\begin{lstlisting}
int main(char argc, char ** argv)
{
	GlowDevice *device = GlowDevice::getInstance();
	device->init(800, 600, false);
	device->setWindowTitle("first window");
	
	Renderer *rdr = device->getRenderer();
	Mesh *myMesh = MeshFactory::create("myFile.off");
	EventManager *emgr = device->getEventManager();
	
	Camera myCamera(Vector3D(3.0,2.0,3.0));
	myCamera.setSensivity(1.0);
	myCamera.setSpeed(5.0);
	
	while(!emgr->quit())
	{
		myCamera.getEvent();
		myCamera.animate();
		
		if (emgr->isKeyDownOnce('a'))
			cout << "The a key is pressed" << endl;
		
		if (emgr->isKeyDown('x')
			cout << "mouse x position : " << emgr->getMouseX();
			
		if (emgr->isKeyDown('y')
			cout << "mouse y position : " << emgr->getMouseY();
		
		myMesh->draw();
		
	}
	delete myMesh;
	GlowDevice::destroy();
	return 0;
}
			\end{lstlisting}

			
			
		\subsection{Loading Options}
		By default the Mesh is loaded in a Vertex Buffer Object (VB0), but if you don't
		want to use it you need to give a second parametter tou the function create. It's
		the boolean value false.
		
		\begin{lstlisting}
Mesh *myMesh = MeshFactory::create("myFile.off", false);
		\end{lstlisting}
		
		But if you prefer to use the VBOs you can just let the file name. It will load
		the mesh in a VBO with the STREAM (GL\_STREAM\_DRAW) update mode. There are three
		differents modes : 
		
		\begin{itemize}
		\item STREAM for GL\_STREAM\_DRAW
		\item DYNAMIC for GL\_DYNAMIC\_DRAW
		\item STATIC for GL\_STATIC\_DRAW
		\end{itemize}
		
		If you don't whant to use the default mode (STREAM), you call the create function
		and give it as the third parameter the mode you want. Note that the second parameter 
		must be true.
	
		\begin{lstlisting}
Mesh *myMesh = MeshFactory::create("myFile.off", true, DYNAMIC);
Mesh *myMesh2 = MeshFactory::create("myFile.off", true, STATIC);
		\end{lstlisting}
			
		\subsection{Texturing the Mesh}
		Your mesh is not really beautyful, you must add a texture to it. It is
		rather simple. Once you have declared your mesh, you can bind a texture to it
		with the function setTexture. You have to give as parameter the path to your texture
		image.
		
		\begin{lstlisting}
myMesh->setTexture("myTexture.png");
		\end{lstlisting}
		
		It must be done one time after declaring the mesh. You don't have to set the 
		texture at each turn of the event loop.
		
		\subsection{Skybox}
		The skybox allows you to embellish your demo. It is a cube which follows your
		camera. You need to give the name of the six sections of tour skybox in this order :
		\begin{itemize}
		\item front
		\item back
		\item down
		\item up
		\item left
		\item right
		\end{itemize}
		
		As welle as the textures, it could be of any common extensions.
		
		\begin{lstlisting}
SkyBox sb;
sb.load("front.png",
		"back.png",
		"down.png",
		"up.png",
		"left.png",
		"right.png");
		\end{lstlisting}
		
		Then at each frame you need to set the skybox's position and center it on the
		camera.
		
		\begin{lstlisting}
sb.setPosition(myCamera.getPosition());	
		\end{lstlisting}
		

		Taking back our example : 
		
		\begin{lstlisting}
int main(char argc, char ** argv)
{
	GlowDevice *device = GlowDevice::getInstance();
	device->init(800, 600, false);
	device->setWindowTitle("first window");
	
	Renderer *rdr = device->getRenderer();
	Mesh *myMesh = MeshFactory::create("myFile.off");
	myMesh->setTexture("myTexture.png"); .
	EventManager *emgr = device->getEventManager();
	
	Camera myCamera(Vector3D(3.0,2.0,3.0));
	myCamera.setSensivity(1.0);
	myCamera.setSpeed(5.0);
	
	SkyBox sb;
	sb.load("front.png",
		"back.png",
		"down.png",
		"up.png",
		"left.png",
		"right.png");
	
	while(!emgr->quit())
	{
		myCamera.getEvent();
		myCamera.animate();
		sb.setPosition(myCamera.getPosition());	
		
		if (emgr->isKeyDownOnce('a'))
			cout << "The a key is pressed" << endl;
		
		if (emgr->isKeyDown('x')
			cout << "mouse x position : " << emgr->getMouseX();
			
		if (emgr->isKeyDown('y')
			cout << "mouse y position : " << emgr->getMouseY();
		
		myMesh->draw();
		
	}
	GlowDevice::destroy();
	return 0;
}
		\end{lstlisting}

	\section{Lighting and Materials}
		\subsection{Lights}
		Once you have a scene and 3D objects loaded in it, you may want to add some realism !
		The Light will tell the scene how it is enlighten. You can precise Four things :
		\begin{itemize}
		\item The light position by the setPosition(Vector3d pos, int infinit) function
		\item The ambient light by the setAmbient(Color4f color) function
		\item The diffuse light by the setDiffuse(Color4f color) function
		\item The specular light by the setSpecular(Color4f color) function
		\end{itemize}
		It is rather simple. If you put something different from 1.0 for the infinit value,
		it means that your light is placed at the infinity, so the Vector is a direction.
		
		\subsection{Materials}
		Now that you have placed your lights, you will have to precise how your objects are interacting
		with it. As well as for the lights, you can precise four values with the Mesh's functions :
		\begin{itemize}
		\item The ambient light by the setAmbient(Color4f color) function
		\item The diffuse light by the setDiffuse(Color4f color) function
		\item The specular light by the setSpecular(Color4f color) function
		\item The shininess by the setSpecular(Color4f color) function
		\end{itemize}
		The shininess will define how big is the specular reflection on the Mesh.

	\section{Shading the Scene}
	If you want to add some more cool effects, like bump mapping or phong shading, you will have no choice than
	use shaders.
	The shaders are very simple to use :
	\begin{lstlisting}
	Shader s("light.vert", "light.frag");
	s.setShader(true);
	// do some draws
	s.setShader(false);
	\end{lstlisting}
	And it is all you need to shade your scene ! Note that you can not use shader AND OpenGL lighting at the same time.
	
\appendix 
\end{document}
